from pathlib import Path
import sys
import subprocess
import traceback
import websocket
import json
import hashlib
import base64
import hmac
import ssl
import _thread as thread
from urllib.parse import urlencode
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
from typing import Dict, Optional
from .base import BaseTTSEngine


class XunfeiTTSEngine(BaseTTSEngine):
    """
    讯飞TTS引擎实现，使用WebSocket API
    """
    
    def __init__(self, config: Optional[Dict] = None):
        super().__init__(config)
        self.has_xunfei_tts = False
        self.app_id = None
        self.api_key = None
        self.secret_key = None
        self.initialize()
    
    def initialize(self) -> bool:
        """
        初始化讯飞TTS引擎
        """
        print("尝试导入讯飞TTS依赖...")
        
        try:
            # 检查必要的库是否可用
            import requests
            print("✓ 导入requests成功")
            
            # 尝试安装websocket-client
            try:
                import websocket
                print("✓ 导入websocket成功")
            except ImportError:
                print("✗ websocket未安装，尝试安装...")
                subprocess.check_call([sys.executable, "-m", "pip", "install", "websocket-client"])
                import websocket
                print("✓ 安装并导入websocket成功")
            
            # 导入其他必要的库
            import hashlib
            import base64
            import hmac
            import ssl
            import _thread as thread
            from urllib.parse import urlencode
            from wsgiref.handlers import format_date_time
            from datetime import datetime
            from time import mktime
            
            print("✓ 导入其他讯飞TTS依赖成功")
            self.has_xunfei_tts = True
            
            # 检查配置
            if self.config:
                self.app_id = self.config.get('app_id')
                self.api_key = self.config.get('api_key')
                self.secret_key = self.config.get('secret_key')
                
                # 验证配置是否有效
                if self.app_id and self.api_key and self.secret_key and self.app_id != "your_app_id":
                    self.initialized = True
                    print("✓ 讯飞TTS引擎初始化成功，配置有效")
                    return True
                else:
                    print("⚠ 讯飞TTS引擎初始化成功，但配置不完整或使用默认值")
                    return True  # 导入成功但配置可能无效
            else:
                print("⚠ 讯飞TTS引擎初始化成功，但未提供配置")
                return True  # 导入成功但配置可能无效
                
        except Exception as e:
            print(f"✗ 无法导入讯飞TTS依赖: {e}")
            print(f"  异常详情: {traceback.format_exc()}")
            return False
    
    def synthesize(self, text: str, output_path: Path, lang: str = "en") -> bool:
        """
        使用讯飞TTS进行语音合成
        """
        if not self.is_available():
            print(f"  ⚠ 讯飞TTS引擎不可用，无法合成文本: {text}")
            return False
        
        # 检查配置是否有效
        if not (self.app_id and self.api_key and self.secret_key and self.app_id != "your_app_id"):
            print("  ⚠ 讯飞TTS配置无效，请检查app_id、api_key和secret_key")
            return False
        
        # 创建WebSocket客户端
        ws_client = XunfeiTTSWebSocketClient(
            self.app_id, 
            self.api_key, 
            self.secret_key,
            text,
            output_path
        )
        
        # 运行合成
        try:
            success = ws_client.run()
            if success:
                print(f"  ✓ 生成音节语音: {text} -> {output_path.name} (讯飞)")
            return success
        except Exception as e:
            print(f"  ⚠ 讯飞TTS异常: {e}")
            return False
    
    def is_available(self) -> bool:
        """
        检查讯飞TTS引擎是否可用
        """
        return self.has_xunfei_tts
    
    def get_name(self) -> str:
        """
        获取引擎名称
        """
        return "xunfei"


class XunfeiTTSWebSocketClient:
    """
    讯飞TTS WebSocket客户端
    """
    
    def __init__(self, app_id, api_key, secret_key, text, output_path):
        self.app_id = app_id
        self.api_key = api_key
        self.secret_key = secret_key
        self.text = text
        self.output_path = output_path
        self.audio_data = bytes()
        self.completed = False
        self.success = False
        self.error_message = None
        self.ws = None
        self.timeout = 10  # 超时时间（秒）
    
    def run(self):
        """
        运行WebSocket客户端
        """
        # 生成WebSocket URL
        ws_url = self._generate_url()
        
        # 创建WebSocket连接
        self.ws = websocket.WebSocketApp(
            ws_url,
            on_open=self.on_open,
            on_message=self.on_message,
            on_error=self.on_error,
            on_close=self.on_close
        )
        
        # 启动WebSocket
        thread.start_new_thread(self._run_forever, ())
        
        # 等待完成或超时
        start_time = time.time()
        while not self.completed:
            if time.time() - start_time > self.timeout:
                self.error_message = "超时: WebSocket连接超时"
                self._close()
                break
            time.sleep(0.1)
        
        return self.success
    
    def _generate_url(self):
        """
        生成WebSocket URL，包含认证信息
        """
        url = "wss://tts-api.xfyun.cn/v2/tts"
        # 生成RFC1123格式的时间戳
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))
        
        # 生成签名
        signature_origin = "host: tts-api.xfyun.cn\ndate: " + date + "\nGET /v2/tts HTTP/1.1"
        signature_sha = hmac.new(self.secret_key.encode('utf-8'), 
                                signature_origin.encode('utf-8'), 
                                digestmod=hashlib.sha256).digest()
        signature = base64.b64encode(signature_sha).decode(encoding='utf-8')
        
        # 生成认证参数
        authorization_origin = f'api_key="{self.api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature}"'
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
        
        # 构造URL参数
        v = urlencode({
            "authorization": authorization,
            "date": date,
            "host": "tts-api.xfyun.cn"
        })
        
        return f"{url}?{v}"
    
    def on_open(self, ws):
        """
        WebSocket连接打开时的回调
        """
        print("  讯飞TTS WebSocket连接已打开")
        
        # 构建请求数据
        data = {
            "common": {
                "app_id": self.app_id
            },
            "business": {
                "aue": "lame",  # MP3格式
                "auf": "audio/L16;rate=16000",  # 音频格式
                "vcn": "xiaoyan",  # 发音人
                "speed": 50,  # 语速
                "pitch": 50,  # 音调
                "volume": 50  # 音量
            },
            "data": {
                "text": base64.b64encode(self.text.encode('utf-8')).decode('utf-8'),
                "status": 2  # 表示文本结束
            }
        }
        
        # 发送数据
        ws.send(json.dumps(data))
    
    def on_message(self, ws, message):
        """
        WebSocket消息处理
        """
        try:
            # 打印接收到的消息
            print(f"  收到讯飞TTS响应消息")
            
            # 解析消息
            resp = json.loads(message)
            
            # 检查字段
            if not isinstance(resp, dict):
                raise ValueError("响应不是有效的JSON对象")
            
            # 检查状态码
            if 'code' in resp:
                if resp['code'] != 0:
                    self.error_message = f"讯飞TTS错误: {resp.get('code')} - {resp.get('message', '未知错误')}"
                    print(f"  {self.error_message}")
                    self._close()
                    return
            
            # 处理音频数据
            if 'data' in resp and isinstance(resp['data'], dict):
                data = resp['data']
                # 安全获取音频数据
                if 'audio' in data and data['audio']:
                    try:
                        audio_content = base64.b64decode(data['audio'])
                        self.audio_data += audio_content
                    except Exception as e:
                        print(f"  解码音频数据失败: {e}")
                
                # 检查是否完成
                if 'status' in data and data['status'] == 2:
                    print("  讯飞TTS合成完成")
                    self._save_audio()
                    self.success = True
                    self._close()
                    return
                    
        except json.JSONDecodeError as e:
            self.error_message = f"解析JSON响应失败: {e}"
            print(f"  {self.error_message}")
            print(f"  原始消息: {message[:100]}...")
        except Exception as e:
            self.error_message = f"处理消息时发生异常: {e}"
            print(f"  {self.error_message}")
            print(f"  异常详情: {traceback.format_exc()}")
    
    def on_error(self, ws, error):
        """
        WebSocket错误处理
        """
        self.error_message = f"讯飞TTS WebSocket错误: {error}"
        print(f"  {self.error_message}")
    
    def on_close(self, ws, close_status_code, close_msg):
        """
        WebSocket连接关闭时的回调
        """
        print(f"  讯飞TTS WebSocket连接已关闭")
        self.completed = True
    
    def _run_forever(self):
        """
        运行WebSocket循环
        """
        try:
            self.ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
        except Exception as e:
            self.error_message = f"WebSocket运行出错: {e}"
            print(f"  {self.error_message}")
    
    def _save_audio(self):
        """
        保存音频数据到文件
        """
        try:
            with open(self.output_path, 'wb') as f:
                f.write(self.audio_data)
            print(f"  音频文件已保存: {self.output_path}")
        except Exception as e:
            self.error_message = f"保存音频文件失败: {e}"
            print(f"  {self.error_message}")
            self.success = False
    
    def _close(self):
        """
        关闭WebSocket连接
        """
        if self.ws:
            try:
                self.ws.close()
            except Exception:
                pass
        self.completed = True


# 导入time模块
import time